package com.zy.gmall0401.cart.service.impl;


import com.alibaba.dubbo.config.annotation.Reference;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;

import com.zy.gmall0401.bean.CartInfo;
import com.zy.gmall0401.bean.SkuInfo;
import com.zy.gmall0401.cart.mapper.CartInfoMapper;

import com.zy.gmall0401.service.CartService;
import com.zy.gmall0401.service.ManageService;
import com.zy.gmall0401.util.RedisUtil;


import jdk.nashorn.internal.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;

import java.math.BigDecimal;
import java.util.*;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    RedisUtil redisUtil;
    @Autowired  //调用本地使用
    CartInfoMapper cartInfoMapper;

    @Reference(check = false)
    ManageService manageService;

    @Override
    //用户登陆情况下保存到购物车
    public CartInfo addCart(String userId, String skuId, Integer num) {

        //添加数据库
        //1.根据已知数据查询数据库
        CartInfo cartInfoQuery = new CartInfo();
        cartInfoQuery.setSkuId(skuId);
        cartInfoQuery.setUserId(userId);
        CartInfo cartInfocar = null;
        cartInfocar = cartInfoMapper.selectOne(cartInfoQuery);//之前购物车数据
        SkuInfo skuInfonew = manageService.getSkuInfo(skuId); //最新商品信息（价格，名字）
        if (cartInfocar != null) {
            //添加购物车的数量
            cartInfocar.setCartPrice(skuInfonew.getPrice());//价格
            cartInfocar.setSkuName(skuInfonew.getSkuName());//商品名字
            cartInfocar.setImgUrl(skuInfonew.getSkuDefaultImg());//默认图片
            cartInfocar.setSkuNum(cartInfocar.getSkuNum() + num); //数量
            cartInfoMapper.updateByPrimaryKey(cartInfocar);//更新购物车数据
        } else {
            //购物车没有直接添加对象
            CartInfo cartInfo = new CartInfo();
            cartInfo.setSkuId(skuId);
            cartInfo.setUserId(userId);
            cartInfo.setSkuNum(num);
            cartInfo.setImgUrl(skuInfonew.getSkuDefaultImg());
            cartInfo.setSkuName(skuInfonew.getSkuName());
            cartInfo.setCartPrice(skuInfonew.getPrice());
            cartInfo.setSkuPrice(skuInfonew.getPrice());

            cartInfoMapper.insertSelective(cartInfo);
            cartInfocar = cartInfo;//赋值
        }

        //把添加到购物车的数据放一份到缓存去
        Jedis jedis = redisUtil.getJedis();
        String cartkey = "cart:" + userId + ":info";
        String carinfojson = JSON.toJSONString(cartInfocar);//把对象转换成字符串
        jedis.hset(cartkey, skuId, carinfojson);//保存到redis
        jedis.close();

        return cartInfocar;
    }

    /*

    查询没有临时购物车，只有登录用户的购物车
     */
    @Override
    public List<CartInfo> cartListold(String userId) {
        List<CartInfo> cartinfos = cartInfoMapper.selectCartListWithSkuPrice(userId);
        return cartinfos;
    }

    @Override
    public List<CartInfo> cartList(String userId) {
        //先查询缓存
        Jedis jedis = redisUtil.getJedis();
        String cartkey = "cart:" + userId + ":info";
        List<String> hvals = jedis.hvals(cartkey);
        List<CartInfo> cartinfos = new ArrayList<>();
        String skuId = null;
        if (hvals != null && hvals.size() > 0) { //缓存命中
            for (String hval : hvals) {
                CartInfo cartInfo = JSON.parseObject(hval, CartInfo.class);
//                查询原来商品的价格存放到skuPrice的参数中去
                skuId = cartInfo.getSkuId();
                SkuInfo skuInfonew = manageService.getSkuInfo(skuId); //最新商品信息（价格，名字）
                BigDecimal price = skuInfonew.getPrice();
                cartInfo.setSkuPrice(price);
                cartinfos.add(cartInfo);
            }
            //把购物车数据进行排序
            cartinfos.sort(new Comparator<CartInfo>() {
                @Override
                public int compare(CartInfo o1, CartInfo o2) {
                    return o2.getId().compareTo(o1.getId());
                }
            });
            return cartinfos;
        } else {//缓存没有数据
            List<CartInfo> cartInfos = loadcartCartch(userId);
            //在查数据库，加载到 缓存 中
            return cartInfos;
        }

    }

    //查询数据库 放到缓存
    public List<CartInfo> loadcartCartch(String userId) {

//        读取数据库
        List<CartInfo> cartInfos = cartInfoMapper.selectCartListWithSkuPrice(userId);
//        写入缓存
        //遍历购物车 转换成map 后放到redis
        if (cartInfos != null && cartInfos.size() > 0) {
            Map<String, String> cartMap = new HashMap<>();
            for (CartInfo cartInfo : cartInfos) {
                cartMap.put(cartInfo.getId(), JSON.toJSONString(cartInfo));

            }
            Jedis jedis = redisUtil.getJedis();
            String cartkey = "cart:" + userId + ":info";
            //对比下购物车价格和原来价格是否有变化

            jedis.hmset(cartkey, cartMap);//redis批量存入数据
            jedis.expire(cartkey, 60 * 60 * 24 * 30);//设置redis过期时间
            jedis.close();

        }
        return cartInfos;
    }

    /**
     * 合并购物车
     *
     * @param userIdDest
     * @param userIdOrig
     * @return
     */
    @Override
    public List<CartInfo> mergeCartList(String userIdDest, String userIdOrig) {
        //1 先做合并
        cartInfoMapper.mergeCartList(userIdDest, userIdOrig);
        // 2 合并后把临时购物车删除
        CartInfo cartInfo = new CartInfo();
        cartInfo.setUserId(userIdOrig);
        cartInfoMapper.delete(cartInfo);
        Jedis jedis = redisUtil.getJedis();
        jedis.del("cart:" + userIdOrig + ":info");
        jedis.close();
        // 3 重新读取数据 加载缓存
        List<CartInfo> cartInfoList = loadCartCache(userIdDest);

        return cartInfoList;
    }


    /**
     * 缓存没有查数据库 ，同时加载到缓存中
     *
     * @param userId
     * @return
     */
    public List<CartInfo> loadCartCache(String userId) {
        // 读取数据库
        List<CartInfo> cartInfoList = cartInfoMapper.selectCartListWithSkuPrice(userId);
        //加载到缓存中
        //为了方便插入redis  把list --> map
        if (cartInfoList != null && cartInfoList.size() > 0) {
            Map<String, String> cartMap = new HashMap<>();
            for (CartInfo cartInfo : cartInfoList) {
                cartMap.put(cartInfo.getSkuId(), JSON.toJSONString(cartInfo));
            }
            Jedis jedis = redisUtil.getJedis();
            String cartKey = "cart:" + userId + ":info";
            jedis.del(cartKey);
            jedis.hmset(cartKey, cartMap);                // hash
            jedis.expire(cartKey, 60 * 60 * 24);
            jedis.close();
        }
        return cartInfoList;

    }

    @Override
    public List<CartInfo> getCheckedCartList(String userId) {
        String cartCheckedKey = "cart:" + userId + ":checked";
        Jedis jedis = redisUtil.getJedis();

        List<String> checkedCartList = jedis.hvals(cartCheckedKey);
        List<CartInfo> cartInfoList = new ArrayList<>();
        for (String cartInfoJson : checkedCartList) {
            CartInfo cartInfo = JSON.parseObject(cartInfoJson, CartInfo.class);
            cartInfoList.add(cartInfo);
        }


        jedis.close();

        return cartInfoList;
    }
    @Override
    public void checkCart(String userId, String skuId, String isChecked) {
        loadCartCacheIfNotExists(userId);// 检查一下缓存是否存在 避免因为缓存失效造成 缓存和数据库不一致

        //  isCheck数据 值保存在缓存中
        //保存标志
        String cartKey = "cart:" + userId + ":info";
        Jedis jedis = redisUtil.getJedis();
        String cartInfoJson = jedis.hget(cartKey, skuId);
        CartInfo cartInfo = JSON.parseObject(cartInfoJson, CartInfo.class);
        cartInfo.setIsChecked(isChecked);
        String cartInfoJsonNew = JSON.toJSONString(cartInfo);
        jedis.hset(cartKey,skuId,cartInfoJsonNew);
        // 为了订单结账 把所有勾中的商品单独 在存放到一个checked购物车中
        String cartCheckedKey = "cart:" + userId + ":checked";
        if(isChecked.equals("1")){  //勾中加入到待结账购物车中， 取消勾中从待结账购物车中删除
            jedis.hset(cartCheckedKey,skuId,cartInfoJsonNew);
            jedis.expire(cartCheckedKey,60*60);
        }else{
            jedis.hdel(cartCheckedKey,skuId);
        }
        jedis.close();

    }
    public void  loadCartCacheIfNotExists(String userId){
        String cartkey="cart:"+userId+":info";
        Jedis jedis = redisUtil.getJedis();
        Long ttl = jedis.ttl(cartkey);
        int ttlInt = ttl.intValue();
        jedis.expire(cartkey,ttlInt+10);
        Boolean exists = jedis.exists(cartkey);
        jedis.close();
        if( !exists){
            loadCartCache( userId);
        }

    }
}
